#include "stdafx.h"
#include "ZClientSocketNetworkController.h"
#include "ZAsyncSocket.h"
#include "ZUtility.h"
#include <memory>

namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
ClientSocketNetworkController::ClientSocketNetworkController(const std::string& address, u_short port, size_t numPooledThread)
:	SocketNetworkController(numPooledThread),
	mSocket(nullptr),
	mAddress(address, port)
{
}

ClientSocketNetworkController::~ClientSocketNetworkController()
{
}

bool ClientSocketNetworkController::start(MessageReceiver* pMessageReceiver)
{
	cleanup();

	if(!SocketNetworkController::start(pMessageReceiver))
		return false;

	std::auto_ptr<AsyncSocket> pSocket(new AsyncSocket(INVALID_SOCKET, SocketNetworkController::initialNetworkId));
	if(!pSocket->create())
		return false;
	if(!pSocket->connect(mAddress.ip(), mAddress.port()))
		return false;
	if(!postCompletionStatus(SocketNetworkController::create, 0, reinterpret_cast<OVERLAPPED*>(pSocket.get())))
		return false;

	pSocket.release();
	return true;
}

void ClientSocketNetworkController::cleanup()
{
	SocketNetworkController::cleanup();

	rwmutex_t::scoped_lock	lock(mSocketLock, true);

	deletePtr(mSocket);
}

bool ClientSocketNetworkController::onCreate(AsyncSocket* pSocket)
{
	if(!SocketNetworkController::onCreate(pSocket))	{
		return false;
	}

	rwmutex_t::scoped_lock	lock(mSocketLock, true);

	mSocket	= pSocket;
	mSocket->reference();
	return mSocket->receive();
}

bool ClientSocketNetworkController::onClose(NetworkId kNetworkId, bool graceful, bool notify)
{
	rwmutex_t::scoped_lock	lock(mSocketLock, true);

	if(!SocketNetworkController::onClose(kNetworkId, graceful, notify))
		return false;

	deletePtr(mSocket);
	return true;
}

bool ClientSocketNetworkController::onIoComplete(NetworkId kNetworkId, size_t bytesTransferred, OVERLAPPED* pOverlapped)
{
//	rwmutex_t::scoped_lock	lock(mSocketLock, false);

	return SocketNetworkController::onIoComplete(kNetworkId, bytesTransferred, pOverlapped);
}

AsyncSocket* ClientSocketNetworkController::getSocket(NetworkId kNetworkId)	const
{
	return mSocket;
}

void ClientSocketNetworkController::send(Stream* pStream, NetworkId kNetworkId)
{
	rwmutex_t::scoped_lock lock(mSocketLock, false);

	SocketNetworkController::send(pStream, kNetworkId);
}

}